在做竞赛时,有一个厉害的模型能让我们提高分数,但除此之外,有一个不可被忽视的工作,那就是数据预处理(preprocessing)。对数据集进行数据清洗和特征工程是一个显示数据处理功力 的工作,它费时耗力且需要经验积累。一个好的预处理会使模型的效果事半功倍。
波士顿房价数据集是回归问题的经典数据集,本文用的是13列的小数据集,用Python对其进行了一些基础的数据处理和可视化操作,简单探索了数据规律和模型的应用。
数据集导入和简单观察
导入数据集后,先大致了解数据集构成、相关信息。下面是一些常规的观察操作,可以选择需要的使用。
1 | #导入必要的包 |
特征名称及解释
- CRIM: per capita crime rate by town 每个城镇人均犯罪率
- ZN: proportion of residential land zoned for lots over 25,000 sq.ft. 超过25000平方英尺用地划为居住用地的百分比
- INDUS: proportion of non-retail business acres per town 非零售商用地百分比
- CHAS: Charles River dummy variable (= 1 if tract bounds river; 0 otherwise) 是否靠近查尔斯河
- NOX: nitric oxides concentration (parts per 10 million) 氮氧化物浓度
- RM: average number of rooms per dwelling 住宅平均房间数目
- AGE: proportion of owner-occupied units built prior to 1940 1940年前建成自用单位比例
- DIS: weighted distances to five Boston employment centres 到5个波士顿就业服务中心的加权距离
- RAD: index of accessibility to radial highways 无障碍径向高速公路指数
- TAX: full-value property-tax rate per $10,000 每万元物业税率
- PTRATIO: pupil-teacher ratio by town 小学师生比例
- B: 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town 黑人比例指数
- LSTAT: % lower status of the population 下层经济阶层比例
- MEDV: Median value of owner-occupied homes in $1000’s 业主自住房屋中值
数据探索性分析EDA和可视化
查看缺失值
1 | df.isnull().any().sum() # 看是否有缺失值 |
输出是0,这份小的数据集是没有缺失值的。
当出现缺失值时,先观察缺失值比例,占比较大的列可以考虑删去。缺失值一般以三种形式存在:NA/NULL/‘ ‘。重要特征的缺失值有时会转化成binary处理,但只限于是否缺失为重要信息的特征。一般的缺失值填充有以下方法:
- 数值型特征:可以用 均值/最大值/最小值/众数 填充
- 时间序列特征:例如苹果今天的价格缺失,可以用昨日的价格填充
- 将缺失值归为一类:可以用不曾出现也不会出现的值,比如:缺失年龄用 999 填充,缺失体重用 -1 填充
- 缺失比例小的连续变量:可用有数值的数据进行对缺失值的回归预测填充,例:班上某同学的身高
填充缺失值是没有固定方法的,需要根据不同的应用场景实际判断。
查看相关性
1 | df.corr # 特征之间的相关性 |
1 | sns.heatmap(df.corr(),square=True,annot=True,cmap='YlGnBu') # 也可以用热力图表示 |
可以发现几个特征之间的相关性特别大,在这个时候,数据的清洗和预处理就更加重要了。由于最后一个变量是房屋的均价,可以把它单独拿出来和其他各个变量做特征,当然也可以在一开始的时候直接使用sns.pairplot(df)
来看每个变量之间的相互关系。
1 | plt.style.use({'figure.figsize':(20,25)}) |
用sklearn筛选重要特征
1 | drop_columns = ['MEDV'] |
输出为Index(['RM', 'PTRATIO', 'LSTAT'], dtype='object')
。此时,可以单独对这几个变量做特征,具体做法因项目和实际需要而定,这里不做具体展开。其他用sklearn进行数据处理的方法可参考:sklearn进行特征选择和数据预处理。
模型应用
关于如何对特征进行整合处理,其实有很多做法,例如分箱、独热编码、归一化等等。在这里,只简单套用一下线性回归和随机森林两个模型,跑出结果。
线性回归
1 | # 分出数据和标签 |
此时模型已经完成了,可以用lin_reg.coef_
查看估计的线性方程系数。也可以用测试集看效果。
1 | from sklearn.metrics import mean_squared_error # 调用均方误差评价指标 |
随机森林
同样用之前分割好的训练集和测试集,代码不再重写。与线性模型代码不同的是,在这里,使用网格搜索交叉验证的方式充分评估回归模型的准确性。
1 | from sklearn.ensemble import RandomForestRegressor |
输出结果
1 | GridSearchCV(cv=3, error_score='raise', |
1 | # 查看效果最好的参数 |
1 | {'max_depth': 7, 'max_features': 0.6, 'n_estimators': 100} |
1 | # 查看效果最好参数对应的模型 |
1 | RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=7, |
可视化一下随机森林的预测结果
1 | result = {"label":y_test,"prediction":rf_reg.predict(X_test)} |
1 | from sklearn.metrics import mean_squared_error # 调用均方误差评价指标 |
可以看出随机森林的结果比线性回归预测要好。